import datetime
import traceback

import redis
import requests
import urllib3
from lxml import html
from urllib3.exceptions import InsecureRequestWarning

from pass_by_selenium import main as by_pass
from setting import *

redis_conn = redis.Redis(host='localhost', port=6379, db=1)

# 关闭 InsecureRequestWarning 警告
urllib3.disable_warnings(InsecureRequestWarning)

session = requests.session()

class CouponException(Exception):

    def __init__(self, message):
        self.message = message
        super().__init__(self)

    def __str__(self):
        return self.message


def get_product_list():
    response = ownRequest(method='GET', url=f'https://www.smzdm.com/jingxuan')

    tree = html.fromstring(response.text)
    # //*[@id="feed-main-list"]/li/div/div/div/div[2]/span/a

    result_lis = []
    """
         if buy_platform == "京东国际":
                buy_platform = "京东"
            elif buy_platform in ["天猫精选", "天猫超市", "天猫国际", "淘宝精选"]:
    """

    # ID 列表
    for _, i in enumerate(tree.xpath('//*[@id="feed-main-list"]/li[@articleid]')):
        id_ = i.xpath("@articleid")[0].replace("3_", "")
        platform_ = i.xpath("div/div/div/div[2]/span/a")[0].text.strip()
        if platform_ not in ["拼多多", "京东国际", "天猫精选", "天猫超市", "天猫国际", "淘宝精选", "京东", "淘宝",
                             "唯品会"]:
            # if platform_ not in ["拼多多", "京东国际", "天猫精选", "天猫超市", "天猫国际", "淘宝精选","京东","淘宝"]:
            print("过滤此平台=> ", platform_)
            continue

        result_lis.append(id_)

    result_lis = [i.replace("3_", "") for i in tree.xpath('//*[@id="feed-main-list"]/li/@articleid')]

    return result_lis

"""
1. 上次使用 proxifier 软件，配置全部走代理+排除代理软件的流量，未正常工作的原因是？换成只单独代理某个指定软件是否可行？
2. 常用流量转发软件的原理分析，如：Sunny Proxifier Postern Droid Wireshark 等
    1. 捕获流量的原理是什么：HOOK收发数据的函数？在驱动层进行流量分流(过滤)？
        1. HOOK方式，优缺点分析：可以直接看到发出和接收的明文数据(无视TLS加密) ，缺点是只能看到无法修改重发HTTPS数据包(除非额外配置中间人攻击或知道某会话使用的密钥)?
        2. 驱动层分流：转发软件依据 IP、PORT、请求发起进程和配置的服务器代理规则，决定如何转发在内核层捕获到的数据包到哪个代理服务器？
    2. 对使用不同代理协议( HTTP(S)/SOCKS )的代理服务器，转发前及转发过程使用怎样的策略/流程？
        1. 关键是在TCP/UDP的握手请求：转发软件遇到握手请求后，重定向为与代理服务器握手，再由代理服务器与目标地址握手(目标地址由转发软件告知，难道不同的代理协议接受的告知方式不同，故需要具体指明代理服务器使用的代理协议？确实是)，而后进行数据转发？这样即使代理软件使用某代理协议的端口收到非本代理协议的数据，也可以正确转发？
        2. HTTP代理协议：UDP数据包不会被转发软件转发给代理服务器;对于携带HTTPS数据和非HTTP数据的TCP报文，会建立两个隧道(转发软件和代理服务器，代理服务器和目标网站)，通过这些隧道透明转发;对于HTTP数据包则直接发送给代理服务器(不需要代理服务器与目标网站先建立连接，代理服务器可以解析后再发送到目标服务器)
        3. HTTPS代理协议：关键在转发软件与代理服务器之间的TCP报文是否加密，需要提前安装/信任证书。
        4. SOCKS代理协议：转发软件将全部的TCP/UDP报文都转发该代理服务器(需要通知代理服务器与哪个目标建立TCP/UDP连接)
3. Charles等代理软件，收到未补全HTTP(S)请求头的代理请求，是否会处理后转发？
    1. 使用 nc 验证，看代理是否正确转发流量
4. 环回地址相关
    1. Wireshark 捕获流量时，捕获到的本地通信(环回数据)数据包都会双份？会收到双份的原因(VM ware分析代理协议时遇到过)？(一份是进一份是出,所以双份？)
    2. 代理软件通过屏蔽代理本地(回环)请求 避免无限循环转发的逻辑 
"""

def ownRequest2(url, method="GET", **args):
    """
    封装请求函数，处理代理超时等错误
    Args:
        url: 请求URL
        **args: 其他请求参数
    Returns:
        response: 请求响应对象
    """

    max_retries = 5  # 最大重试次数
    retry_count = 0

    while retry_count < max_retries:
        try:
            if method == "GET":
                response = requests.get(url, **args)
                return response
            elif method == "POST":
                response = requests.post(url, **args)
                return response
        except requests.exceptions.ProxyError:
            print(f"代理错误，正在重试 ({retry_count + 1}/{max_retries})")
            retry_count += 1
            # time.sleep(2)  # 等待2秒后重试

        except requests.exceptions.ConnectTimeout:
            print(f"连接超时，正在重试 ({retry_count + 1}/{max_retries})")
            retry_count += 1

        except requests.exceptions.ReadTimeout:
            print(f"读取超时，正在重试 ({retry_count + 1}/{max_retries})")
            retry_count += 1

        except requests.exceptions.RequestException as e:
            print(f"请求异常: {str(e)}，正在重试 ({retry_count + 1}/{max_retries})")
            retry_count += 1
        except requests.exceptions.SSLError:
            print(f"SSL错误，正在重试 ({retry_count + 1}/{max_retries})")
            retry_count += 1
        except:
            print(f"未知错误，正在重试 ({retry_count + 1}/{max_retries})")
            retry_count += 1

    # 如果所有重试都失败了
    print(f"请求失败，已重试{max_retries}次")
    return None
    # raise requests.exceptions.RequestException(f"请求失败，已重试{max_retries}次")


def ownRequest(method, **kwargs):
    global session
    try:
        if method == "GET":
            # response = session.get(headers=HEADERS, cookies=COOKIES, proxies=PROXIES,verify=False,**kwargs)
            # 使用selenium绕过验证码后指定了session 的cookie  在发送请求的时候就不能再指定cookie 否则先前的cookie会失效？？？？
            response = session.get(headers=HEADERS, proxies=PROXIES, verify=False, **kwargs)
        else:
            # response = session.get(headers=HEADERS, cookies=COOKIES, proxies=PROXIES,verify=False,**kwargs)
            response = session.post(headers=HEADERS, proxies=PROXIES, verify=False, **kwargs)

        # 判断是否出现滑块  若出现则调用滑块处理逻辑
        if "https://ssl.captcha.qq.com/TCaptcha.js" in response.text or 'var buid = "fffffffffffffffffff"\n' in response.text:
            print("出现滑块=> ", response.url, "cookies=> ", session.cookies.items())

            # 方案一  由selenium通过滑块后 传递新的cookie使用 获取selenium处理后的cookies并更新到session中
            selenium_cookies = by_pass.bypass_selenium(session.cookies, by_pass.DRIVER)
            # 直接新建一个seession对象
            session = requests.session()  # 使用新的session  也许现在可以去掉了？

            # 或者是删除session中的cookie数据
            # session.cookies.clear()
            for cookie in selenium_cookies:
                session.cookies.set(cookie['name'], cookie['value'])

            # 方案二  将session出现滑块的cookie传递给selenium 由selenium通过滑块即可 这种方式也就不用再将cookie写回session
            #  这种方式害怕一直使用同一个CK去请求数据会出现其它限制
            # selenium_cookies = by_pass.bypass_selenium(session.cookies,by_pass.DRIVER)

        return response

    except Exception as e:
        traceback.print_exc()
        return None


def get_sec_timestamp(timestamp):
    # 转换为本地时间（如北京时间 UTC+8）
    local_time = datetime.datetime.fromtimestamp(int(timestamp) / 1000)
    formatted_time = local_time.strftime("%Y-%m-%d %H:%M:%S")
    return formatted_time


def get_post_shop_jie_xi(shop_url_other):
    # 获取商品ID,通过解析接口
    jie_xi_url = "http://cgi-bin.lottefuture.com/python/link-parse.php"
    json1 = {
        "content": shop_url_other,
    }

    # 经常时间超时 重试后又可以通过 尝试延长时间
    for i in range(5):
        try:
            shop_post_link_response = requests.post(jie_xi_url, json=json1, timeout=3)
            break
        except Exception as e:
            print("异常信息=>", e)
            continue
    end_shop_detail_result = shop_post_link_response.json()
    return end_shop_detail_result


def get_you_hui_timeout(you_hui_tiao_zhuan_link):
    # 获取商品ID,通过解析接口
    jing_dong_you_jie_xi_url = f"http://cgi-bin.lottefuture.com/python/jd-coupon-query.php?url={you_hui_tiao_zhuan_link}"
    params = {
        "content": you_hui_tiao_zhuan_link,
    }

    shop_post_link_response = requests.get(jing_dong_you_jie_xi_url, params=params, timeout=3)
    jing_dong_you_hui_details = shop_post_link_response.json()
    huo_dong_all_msg = jing_dong_you_hui_details.get("data")

    for huo in huo_dong_all_msg:
        huo_dong_begin_time = huo.get("beginTime")
        huo_dong_begin_time = get_sec_timestamp(huo_dong_begin_time)
        huo_dong_end_time = huo.get("endTime")
        huo_dong_end_time = get_sec_timestamp(huo_dong_end_time)
        huo_dong_time = {
            "huo_dong_begin_time": huo_dong_begin_time,
            "huo_dong_end_time": huo_dong_end_time
        }

    return huo_dong_time





if __name__ == '__main__':
    # you_hui_tiao_zhuan_link = "https://coupon.m.jd.com/coupons/show.action?linkKey=AAROH_xIpeffAs_-naABEFoexrYcD5guWNM8szF_NmlSDD19oKwMhgRo8qtqG7fKNnP1HuFDeqE-VuienBCH4Vk34ga_6w"
    # print(get_you_hui_timeout(you_hui_tiao_zhuan_link))
    l = get_product_list()
    print(l)
